package cn.iocoder.yudao.module.brokerage.record.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.iocoder.yudao.framework.util.TransactionUtils;
import cn.iocoder.yudao.module.api.brokerage.record.dto.BrokerageRecordSaveDTO;
import cn.iocoder.yudao.module.api.brokerage.record.enums.BrokerageBonusLevelEnum;
import cn.iocoder.yudao.module.api.brokerage.record.enums.BrokerageRecordBizTypeEnum;
import cn.iocoder.yudao.module.api.brokerage.record.enums.BrokerageRecordStatusEnum;
import cn.iocoder.yudao.module.api.infrastructure.config.ConfigApiV2;
import cn.iocoder.yudao.module.api.infrastructure.config.dto.BrokerageConfigRespDTO;
import cn.iocoder.yudao.module.api.member.agency.AgencyUserApi;
import cn.iocoder.yudao.module.api.member.agency.vo.AgencyOrderVO;
import cn.iocoder.yudao.module.api.member.vip.vo.VipOrderVO;
import cn.iocoder.yudao.module.api.shop.info.ShopInfoApi;
import cn.iocoder.yudao.module.api.trade.order.TradeOrderApi;
import cn.iocoder.yudao.module.api.trade.order.dto.TradeOrderItemRespDTO;
import cn.iocoder.yudao.module.api.trade.order.dto.TradeOrderRespDTO;
import cn.iocoder.yudao.module.api.trade.scan.dto.ScanOrderDTO;
import cn.iocoder.yudao.module.brokerage.record.convert.BrokerageRecordConvert;
import cn.iocoder.yudao.module.brokerage.record.dao.BrokerageRecordMapper;
import cn.iocoder.yudao.module.brokerage.record.mq.BrokerageRecordProducer;
import cn.iocoder.yudao.module.brokerage.record.pojo.po.BrokerageRecordDO;
import cn.iocoder.yudao.module.brokerage.user.dao.BrokerageUserMapper;
import cn.iocoder.yudao.module.brokerage.user.pojo.po.BrokerageUserDO;
import jakarta.annotation.Nullable;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import static cn.iocoder.yudao.module.api.infrastructure.ConfigConstants.CONFIG_BROKERAGE;

/**
 * 佣金记录 Service 实现类
 *
 * @author owen
 * @author 山野羡民
 */
@Slf4j
@Service
@Validated
public class BrokerageRecordServiceImpl implements BrokerageRecordService {

    @Resource
    private BrokerageRecordMapper brokerageRecordMapper;
    @Resource
    private BrokerageUserMapper brokerageUserMapper;

    @Resource
    private BrokerageRecordProducer brokerageRecordProducer;

    @Resource
    @Lazy // 延迟加载，避免循环依赖
    private ConfigApiV2 configApiV2;
    @Resource
    @Lazy // 延迟加载，避免循环依赖
    private TradeOrderApi tradeOrderApi;
    /*@Resource
    @Lazy // 延迟加载，避免循环依赖
    private VipUserApi vipUserApi;*/
    @Resource
    @Lazy // 延迟加载，避免循环依赖
    private AgencyUserApi agencyUserApi;
    @Resource
    @Lazy // 延迟加载，避免循环依赖
    private ShopInfoApi shopInfoApi;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addBrokerageWhenOrderPaid(TradeOrderRespDTO order) {
        // 用户下单时填写了推广用户，则给该用户分佣
        if (order.getBrokerageUserId() != null && order.getBrokerageUserId() > 0) {
            BrokerageUserDO brokerageUserDO = brokerageUserMapper.findByUserId(order.getBrokerageUserId());
            if (brokerageUserDO == null || brokerageUserDO.getUserId() == null || brokerageUserDO.getUserId() <= 0) {
                log.warn("[addBrokerageWhenOrderPaid/TradeOrder] 用户({})下单({})，绑定的推广人({})信息缺失", order.getUserId(), order.getNo(), order.getBrokerageUserId());
                return;
            }
            log.info("[addBrokerageWhenOrderPaid/TradeOrder] 用户({})下单({})，支付成功给绑定的推广人({})分佣", order.getUserId(), order.getNo(), order.getBrokerageUserId());
            addBrokerage(BrokerageBonusLevelEnum.FATHER, order.getBrokerageUserId(), order);
        } else {
            log.debug("[addBrokerageWhenOrderPaid/TradeOrder] 用户({})下单({})没有绑定的推广人信息", order.getUserId(), order.getNo());
        }
        // 用户下单时，无论是否通过推广人的链接进来，上级推广人及上上级推广人都分佣
        BrokerageUserDO user = brokerageUserMapper.findByUserId(order.getUserId());
        if (user == null || user.getUserId() == null || user.getUserId() <= 0) {
            log.warn("[addBrokerageWhenOrderPaid/TradeOrder] 用户({})下单({})，下单用户对应的推广人信息缺失", order.getUserId(), order.getNo());
            return;
        }
        log.info(" [addBrokerageWhenOrderPaid/TradeOrder]用户({})下单({})，支付成功给相关推广人({})分佣", order.getUserId(), order.getNo(), user.getUserId());
        boolean handled = addBrokerage(BrokerageBonusLevelEnum.FATHER, user.getFatherUserId(), order);
        Long grandpaUserId = user.getGrandpaUserId();
        if (handled && (grandpaUserId == null || grandpaUserId <= 0)) {
            BrokerageUserDO grandpaUser = brokerageUserMapper.findByUserId(user.getFatherUserId());
            if (grandpaUser.getFatherUserId() > 0) {
                grandpaUserId = grandpaUser.getFatherUserId();
            }
        }
        if (addBrokerage(BrokerageBonusLevelEnum.GRANDPA, grandpaUserId, order)) {
            handled = true;
        }
        if (!handled) {
            log.warn("[addBrokerageWhenOrderPaid/TradeOrder] 没有上级推广人：{}", user);
        }
    }

    private boolean addBrokerage(BrokerageBonusLevelEnum bonusLevel, Long brokerageUserId, TradeOrderRespDTO order) {
        if (brokerageUserId == null || brokerageUserId <= 0) {
            return false;
        }
        String note = null;
        boolean valid = true;
        BrokerageUserDO brokerageUserDO = brokerageUserMapper.findByUserId(brokerageUserId);
        if (brokerageUserDO.getUserId() == null || brokerageUserDO.getUserId() <= 0L) {
            log.warn("[addBrokerage/TradeOrder] 上级推广人({})不存在推广人信息", brokerageUserId);
            note = "消费分佣无效：未获取到上级推广人信息";
            valid = false;
        } else if (!Boolean.TRUE.equals(brokerageUserDO.getEnabled())) {
            log.warn("[addBrokerage/TradeOrder] 上级推广人({})的分佣资格未启用", brokerageUserId);
            note = "消费分佣无效：推广分佣资格未启用";
            valid = false;
        }
        addBrokerage(bonusLevel, brokerageUserId, order, note, valid);
        return true;
    }

    private void addBrokerage(BrokerageBonusLevelEnum bonusLevel, Long brokerageUserId, TradeOrderRespDTO order, String note, boolean valid) {
        List<TradeOrderItemRespDTO> orderItems = tradeOrderApi.getOrderItemsByOrderId(order.getId());
        if (CollUtil.isEmpty(orderItems)) {
            log.error("[addBrokerage/TradeOrder][订单项不存在，userId({}) orderItemIds({})", brokerageUserId, orderItems.stream().mapToLong(TradeOrderItemRespDTO::getId).toArray());
            note = "消费分佣无效：订单项不存在";
            valid = false;
        }
        BrokerageConfigRespDTO config = configApiV2.getConfig(CONFIG_BROKERAGE, BrokerageConfigRespDTO.class);
        if (valid && !config.isEnabled()) {
            log.error("[addBrokerage/TradeOrder][推广分佣功能未开启，userId({}) orderItemIds({})", brokerageUserId, orderItems.stream().mapToLong(TradeOrderItemRespDTO::getId).toArray());
            note = "消费分佣无效：推广分佣功能未开启";
            valid = false;
        }
        try {
            double bonusPercent = 0D;
            if (Objects.equals(bonusLevel.getValue(), BrokerageBonusLevelEnum.FATHER.getValue())) {
                bonusPercent = config.getFatherPercent();
            } else if (Objects.equals(bonusLevel.getValue(), BrokerageBonusLevelEnum.GRANDPA.getValue())) {
                bonusPercent = config.getGrandpaPercent();
            }
            List<BrokerageRecordSaveDTO> list = new ArrayList<>(orderItems.size());
            // 每一个订单项都去生成分佣记录以便于退款时扣除已分配的佣金
            for (TradeOrderItemRespDTO orderItem : orderItems) {
                BrokerageRecordSaveDTO dto = new BrokerageRecordSaveDTO();
                dto.setBizType(BrokerageRecordBizTypeEnum.BUY_PRODUCT.getCode());
                dto.setBizId(order.getNo() + "@" + orderItem.getId());
                //vo.setBasePrice(valid ? orderItem.getPrice() * orderItem.getCount() : 0); // 使用订单原价作为基准金额
                dto.setBasePrice(valid ? orderItem.getPayPrice() : 0); // 使用订单实付款作为基准金额
                dto.setBonusLevel(bonusLevel.getValue());
                dto.setBonusPercent(bonusPercent);
                dto.setSourceUserId(orderItem.getUserId());
                dto.setNote(note);
                list.add(dto);
            }
            List<BrokerageRecordDO> records = BrokerageRecordConvert.INSTANCE.convertList(brokerageUserId, list);
            brokerageRecordMapper.insertBatch(records);
        } catch (Exception e) {
            log.error("[addBrokerage/TradeOrder] 消费分佣出错", e);
        }
    }


    @Override
    public void addBrokerageWhenOrderPaid(ScanOrderDTO order) {
        // 用户扫码下单支付时，上级推广人及上上级推广人都分佣
        BrokerageUserDO user = brokerageUserMapper.findByUserId(order.getUserId());
        if (user == null || user.getUserId() == null) {
            log.warn("[addBrokerageWhenOrderPaid/ScanOrder] 用户({})下单({})，下单用户对应的推广人信息缺失", order.getUserId(), order.getTradeNo());
            return;
        }
        log.info(" [addBrokerageWhenOrderPaid/ScanOrder]用户({})下单({})，支付成功给相关推广人({})分佣", order.getUserId(), order.getTradeNo(), user);
        boolean handled = addBrokerage(BrokerageBonusLevelEnum.FATHER, user.getFatherUserId(), order);
        if (addBrokerage(BrokerageBonusLevelEnum.GRANDPA, user.getGrandpaUserId(), order)) {
            handled = true;
        }
        if (!handled) {
            log.warn("[addBrokerageWhenOrderPaid/ScanOrder] 没有上级推广人：{}", user);
        }
    }

    private boolean addBrokerage(BrokerageBonusLevelEnum bonusLevel, Long brokerageUserId, ScanOrderDTO order) {
        if (brokerageUserId == null || brokerageUserId <= 0) {
            return false;
        }
        String note = null;
        boolean valid = true;
        BrokerageUserDO brokerageUserDO = brokerageUserMapper.findByUserId(brokerageUserId);
        if (brokerageUserDO == null || brokerageUserDO.getUserId() == null) {
            log.warn("[addBrokerage/ScanOrder] 上级推广人({})不存在推广人信息", brokerageUserId);
            note = "消费分佣无效：未获取到上级推广人信息";
            valid = false;
        } else if (!Boolean.TRUE.equals(brokerageUserDO.getEnabled())) {
            log.warn("[addBrokerage/ScanOrder] 上级推广人({})的分佣资格未启用", brokerageUserId);
            note = "消费分佣无效：推广分佣资格未启用";
            valid = false;
        }
        addBrokerage(bonusLevel, brokerageUserId, order, note, valid);
        return true;
    }

    private void addBrokerage(BrokerageBonusLevelEnum bonusLevel, Long brokerageUserId, ScanOrderDTO order, String note, boolean valid) {
        BrokerageConfigRespDTO config = configApiV2.getConfig(CONFIG_BROKERAGE, BrokerageConfigRespDTO.class);
        if (valid && !config.isEnabled()) {
            log.error("[addBrokerage/ScanOrder][推广分佣功能未开启，userId({}) tradeNo({})", brokerageUserId, order.getTradeNo());
            note = "消费分佣无效：推广分佣功能未开启";
            valid = false;
        }
        try {
            double bonusPercent = 0D;
            if (Objects.equals(bonusLevel.getValue(), BrokerageBonusLevelEnum.FATHER.getValue())) {
                bonusPercent = config.getFatherPercent();
            } else if (Objects.equals(bonusLevel.getValue(), BrokerageBonusLevelEnum.GRANDPA.getValue())) {
                bonusPercent = config.getGrandpaPercent();
            }
            BrokerageRecordSaveDTO dto = new BrokerageRecordSaveDTO();
            dto.setBizType(BrokerageRecordBizTypeEnum.OFFLINE_SCAN_ORDER.getCode());
            dto.setBizId(order.getTradeNo());
            dto.setBasePrice(valid ? order.getPrice() : 0);
            dto.setBonusLevel(bonusLevel.getValue());
            dto.setBonusPercent(bonusPercent);
            dto.setSourceUserId(order.getUserId());
            dto.setNote(note);
            List<BrokerageRecordDO> records = BrokerageRecordConvert.INSTANCE.convertList(brokerageUserId, Collections.singletonList(dto));
            brokerageRecordMapper.insertBatch(records);
        } catch (Exception e) {
            log.error("[addBrokerage/ScanOrder] 扫码付款分佣出错", e);
        }
    }

    @Override
    public void addBrokerageWhenOrderPaid(VipOrderVO order) {
        /*BrokerageUser brokerageUser = brokerageUserMapper.findByUserId(order.getUserId());
        if (brokerageUser == null || brokerageUser.getUserId() == null) {
            log.error("[addBrokerageWhenOrderPaid/VipOrder] 用户({})购买会员({})，对应的推广人信息缺失", order.getUserId(), order.getTradeNo());
            return;
        }
        log.info("[addBrokerageWhenOrderPaid/VipOrder] 用户({})购买会员({})，支付成功给相关推广人({})分佣", order.getUserId(), order.getTradeNo(), brokerageUser);
        boolean handled = addBrokerage(BrokerageBonusLevelEnum.FATHER, brokerageUser.getFatherUserId(), order);
        if (addBrokerage(BrokerageBonusLevelEnum.GRANDPA, brokerageUser.getGrandpaUserId(), order)) {
            handled = true;
        }
        if (!handled) {
            log.warn("[addBrokerageWhenOrderPaid/VipOrder] 没有上级推广人：fatherUserId={}, grandpaUserId={}", brokerageUser.getFatherUserId(), brokerageUser.getGrandpaUserId());
        }*/
        // 2025/05/09 需求变更：取消会员费的二级分佣（15%+5%），充会员来源于哪个商家则哪个商家分（20%）
        Long shopId = order.getFromShopId();
        if (shopId == null || shopId <= 0) {
            log.error("[addBrokerageWhenOrderPaid/VipOrder] 用户({})购买会员({})，对应的推广商家店铺信息缺失", order.getUserId(), order.getTradeNo());
            return;
        }
        Long userId = shopInfoApi.getOwnerMemberUserId(shopId);
        if (userId == null || userId <= 0) {
            log.error("[addBrokerageWhenOrderPaid/VipOrder] 用户({})购买会员({})，对应的推广商家({})用户信息缺失", order.getUserId(), order.getTradeNo(), shopId);
            return;
        }
        addBrokerage(BrokerageBonusLevelEnum.FATHER, userId, order, null, true);
    }

    /*private boolean addBrokerage(BrokerageBonusLevelEnum bonusLevel, Long brokerageUserId, VipOrderVO order) {
        if (brokerageUserId == null || brokerageUserId <= 0) {
            return false;
        }
        String note = null;
        boolean valid = true;
        BrokerageUser brokerageUser = brokerageUserMapper.findByUserId(brokerageUserId);
        if (brokerageUser == null || brokerageUser.getUserId() == null) {
            log.warn("[addBrokerage/VipOrder] 上级推广人({})不存在推广人信息", brokerageUserId);
            note = "会员费分佣无效：未获取到上级推广人信息";
            valid = false;
        } else if (Boolean.TRUE.equals(brokerageUser.getEnabled())) {
            boolean enabled = false;
            if (vipUserApi.validVip(brokerageUserId, null)) {
                enabled = true;
            } else if (shopInfoApi.isOwnerByMemberUserId(brokerageUserId)) {
                enabled = true;
            } else if (agencyUserApi.validAgency(brokerageUserId, null)) {
                enabled = true;
            }
            if (!enabled) {
                note = "会员费分佣无效：还不是会员、商家或招商人员";
                valid = false;
            }
        } else {
            log.warn("[addBrokerage/VipOrder] 上级推广人({})的分佣资格未启用", brokerageUserId);
            note = "会员费分佣无效：推广分佣资格未启用";
            valid = false;
        }
        addBrokerage(bonusLevel, brokerageUserId, order, note, valid);
        return true;
    }*/

    @SuppressWarnings("SameParameterValue")
    private void addBrokerage(BrokerageBonusLevelEnum bonusLevel, Long brokerageUserId, VipOrderVO order, String note, boolean valid) {
        BrokerageConfigRespDTO config = configApiV2.getConfig(CONFIG_BROKERAGE, BrokerageConfigRespDTO.class);
        if (valid && !config.isEnabled()) {
            log.error("[addBrokerage/VipOrder][推广分佣功能未开启，brokerageUserId({}) tradeNo({})", brokerageUserId, order.getTradeNo());
            note = "会员费分佣无效：推广分佣功能未开启";
            valid = false;
        }
        try {
            double bonusPercent = 0D;
            if (Objects.equals(bonusLevel.getValue(), BrokerageBonusLevelEnum.FATHER.getValue())) {
                bonusPercent = config.getVipFeeFatherPercent();
            } else if (Objects.equals(bonusLevel.getValue(), BrokerageBonusLevelEnum.GRANDPA.getValue())) {
                bonusPercent = config.getVipFeeGrandpaPercent();
            }
            BrokerageRecordSaveDTO dto = new BrokerageRecordSaveDTO();
            dto.setBizType(BrokerageRecordBizTypeEnum.BUY_VIP.getCode());
            dto.setBizId(String.valueOf(order.getTradeNo()));
            dto.setBasePrice(valid ? order.getPrice() : 0);
            dto.setBonusLevel(bonusLevel.getValue());
            dto.setBonusPercent(bonusPercent);
            dto.setSourceUserId(order.getUserId());
            dto.setNote(note);
            List<BrokerageRecordDO> records = BrokerageRecordConvert.INSTANCE.convertList(brokerageUserId, Collections.singletonList(dto));
            brokerageRecordMapper.insertBatch(records);
        } catch (Exception e) {
            log.error("[addBrokerage/VipOrder] 会员费分佣出错", e);
        }
    }

    @Override
    public void addBrokerageWhenOrderPaid(AgencyOrderVO order) {
        BrokerageUserDO brokerageUserDO = brokerageUserMapper.findByUserId(order.getUserId());
        if (brokerageUserDO == null || brokerageUserDO.getUserId() == null) {
            log.error("[addBrokerageWhenOrderPaid/AgencyOrder] 用户({})缴纳入驻费({})，对应的推广人信息缺失", order.getUserId(), order.getTradeNo());
            return;
        }
        log.info("[addBrokerageWhenOrderPaid/AgencyOrder] 用户({})缴纳入驻费({})，支付成功给相关推广人({})分佣", order.getUserId(), order.getTradeNo(), brokerageUserDO);
        boolean handled = addBrokerage(brokerageUserDO, BrokerageBonusLevelEnum.FATHER, brokerageUserDO.getFatherUserId(), order);
        if (addBrokerage(brokerageUserDO, BrokerageBonusLevelEnum.GRANDPA, brokerageUserDO.getGrandpaUserId(), order)) {
            handled = true;
        }
        if (!handled) {
            log.warn("[addBrokerageWhenOrderPaid/AgencyOrder] 没有上级推广人：{}", brokerageUserDO);
        }
    }

    private boolean addBrokerage(BrokerageUserDO user, BrokerageBonusLevelEnum bonusLevel, Long brokerageUserId, AgencyOrderVO order) {
        if (brokerageUserId == null || brokerageUserId <= 0) {
            return false;
        }
        String note = null;
        boolean valid = true;
        BrokerageUserDO brokerageUserDO = brokerageUserMapper.findByUserId(brokerageUserId);
        if (brokerageUserDO == null || brokerageUserDO.getUserId() == null) {
            log.warn("[addBrokerage/AgencyOrder] 上级推广人({})不存在推广人信息", brokerageUserId);
            note = "入驻费分佣无效：未获取到上级推广人信息";
            valid = false;
        } else if (Boolean.TRUE.equals(brokerageUserDO.getEnabled())) {
            if (!agencyUserApi.validAgency(brokerageUserId, null)) {
                log.warn("[addBrokerage/AgencyOrder] 上级推广人({})还不是招商人员身份", brokerageUserId);
                note = "入驻费分佣无效：还不是招商人员身份";
                valid = false;
            } else if (brokerageUserDO.getLevelWeight() < user.getLevelWeight()) {
                log.warn("[addBrokerage/AgencyOrder] 下({})推上({})不能分佣", user.getUserId(), brokerageUserId);
                note = "入驻费分佣无效：下推上";
                valid = false;
            }
        } else {
            log.warn("[addBrokerage/AgencyOrder] 上级推广人({})的分佣资格未启用", brokerageUserId);
            note = "入驻费分佣无效：推广分佣资格未启用";
            valid = false;
        }
        addBrokerage(bonusLevel, brokerageUserId, order, note, valid);
        return true;
    }

    private void addBrokerage(BrokerageBonusLevelEnum bonusLevel, Long brokerageUserId, AgencyOrderVO order, String note, boolean valid) {
        BrokerageConfigRespDTO config = configApiV2.getConfig(CONFIG_BROKERAGE, BrokerageConfigRespDTO.class);
        if (valid && !config.isEnabled()) {
            log.warn("[addBrokerage/AgencyOrder][推广分佣功能未开启，brokerageUserId({}) tradeNo({})", brokerageUserId, order.getTradeNo());
            note = "入驻费分佣无效：推广分佣功能未开启";
            valid = false;
        }
        try {
            double bonusPercent = 0D;
            if (Objects.equals(bonusLevel.getValue(), BrokerageBonusLevelEnum.FATHER.getValue())) {
                bonusPercent = config.getAgencyFeeFatherPercent();
            } else if (Objects.equals(bonusLevel.getValue(), BrokerageBonusLevelEnum.GRANDPA.getValue())) {
                bonusPercent = config.getAgencyFeeGrandpaPercent();
            }
            BrokerageRecordSaveDTO dto = new BrokerageRecordSaveDTO();
            dto.setBizType(BrokerageRecordBizTypeEnum.BUY_AGENCY.getCode());
            dto.setBizId(String.valueOf(order.getTradeNo()));
            dto.setBasePrice(valid ? order.getPrice() : 0);
            dto.setBonusLevel(bonusLevel.getValue());
            dto.setBonusPercent(bonusPercent);
            dto.setSourceUserId(order.getUserId());
            dto.setNote(note);
            List<BrokerageRecordDO> records = BrokerageRecordConvert.INSTANCE.convertList(brokerageUserId, Collections.singletonList(dto));
            brokerageRecordMapper.insertBatch(records);
        } catch (Exception e) {
            log.error("[addBrokerage/AgencyOrder] 入驻费分佣出错", e);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void cancelBrokerage(TradeOrderRespDTO order, TradeOrderItemRespDTO orderItem) {
        if (order.getBrokerageUserId() != null && order.getBrokerageUserId() > 0) {
            log.info("[cancelBrokerage] 用户({})订单单项({})退款，取消下单时填写的推荐人用户({})的分佣", order.getUserId(), orderItem.getId(), order.getBrokerageUserId());
            cancelBrokerage(order.getBrokerageUserId(), order.getNo(), orderItem.getId());
        }
        BrokerageUserDO brokerageUserDO = brokerageUserMapper.findByUserId(order.getUserId());
        if (brokerageUserDO != null && brokerageUserDO.getFatherUserId() != null && brokerageUserDO.getFatherUserId() > 0) {
            log.info("[cancelBrokerage] 用户({})订单单项({})退款，取消上级推广人({})的分佣", order.getUserId(), orderItem.getId(), brokerageUserDO.getFatherUserId());
            cancelBrokerage(brokerageUserDO.getFatherUserId(), order.getNo(), orderItem.getId());
        }
        if (brokerageUserDO != null && brokerageUserDO.getGrandpaUserId() != null && brokerageUserDO.getGrandpaUserId() > 0) {
            log.info("[cancelBrokerage] 用户({})订单单项({})退款，取消上上级推广人({})的分佣", order.getUserId(), orderItem.getId(), brokerageUserDO.getGrandpaUserId());
            cancelBrokerage(brokerageUserDO.getGrandpaUserId(), order.getNo(), orderItem.getId());
        }
    }

    private void cancelBrokerage(Long userId, String tradeNo, @Nullable Long orderItemId) {
        String bizId = tradeNo;
        if (orderItemId != null && orderItemId > 0) {
            bizId += "@" + orderItemId;
        }
        List<BrokerageRecordDO> records = brokerageRecordMapper.selectByBizTypeAndBizId(BrokerageRecordBizTypeEnum.BUY_PRODUCT.getCode(), bizId);
        if (CollUtil.isEmpty(records)) {
            log.error("[cancelBrokerage][userId({})] orderItemId({}) 更新佣金记录为已取消失败：记录不存在]", userId, orderItemId);
            return;
        }
        for (BrokerageRecordDO record : records) {
            // 更新佣金记录为已取消
            BrokerageRecordDO updateObj = new BrokerageRecordDO();
            updateObj.setStatus(BrokerageRecordStatusEnum.CANCEL.getValue());
            updateObj.setCancelTime(LocalDateTime.now());
            int updateRows = brokerageRecordMapper.updateByIdAndStatus(record.getId(), record.getStatus(), updateObj);
            if (updateRows == 0) {
                log.error("[cancelBrokerage][record({}) 更新佣金记录为已取消失败]", record.getId());
                return;
            }
            log.info("[cancelBrokerage][userId({})][orderItemId({}) 更新佣金记录为已取消成功]", userId, orderItemId);
            if (!BrokerageRecordStatusEnum.UNFREEZE.getValue().equals(record.getStatus())) {
                return;
            }
            // 减少用户的累计业绩、累计佣金
            updateRows = brokerageUserMapper.decreaseBonusMoney(record.getUserId(), record.getBasePrice(), record.getBonusMoney());
            log.info("[cancelBrokerage][userId({})][orderItemId({}) 更新用户的累计佣金结果：{}]", userId, orderItemId, updateRows > 0);
            if (updateRows == 0) {
                return;
            }
            brokerageRecordProducer.sendCommissionCancelMessage(record.getUserId(), tradeNo, record.getBasePrice(), record.getBonusMoney());
        }
    }

    @Override
    public int unfreezeUserRecord() {
        // 1. 查询待解冻的佣金记录
        List<BrokerageRecordDO> records = brokerageRecordMapper.selectListByStatusAndLessThanUnfreezeTime(
                BrokerageRecordStatusEnum.FREEZING.getValue(), LocalDateTime.now());
        if (CollUtil.isEmpty(records)) {
            log.debug("[unfreezeUserRecord][无待解冻的佣金记录]");
            return 0;
        }
        // 2. 遍历执行
        int count = 0;
        for (BrokerageRecordDO record : records) {
            try {
                if (SpringUtil.getBean(getClass()).unfreezeUserRecord(record)) {
                    count++;
                }
            } catch (Exception e) {
                log.error("[unfreezeUserRecord][record({}) 更新为已结算失败]", record.getId(), e);
            }
        }
        log.info("[unfreezeUserRecord][count({})]", count);
        return count;
    }

    /**
     * 解冻单条佣金记录
     *
     * @return 解冻是否成功
     */
    @Override
    public boolean unfreezeUserRecord(BrokerageRecordDO record) {
        Boolean result = TransactionUtils.transactional(() -> {
            // 更新记录状态
            BrokerageRecordDO updateObj = new BrokerageRecordDO();
            if (record.getBonusMoney() <= 0) {
                updateObj.setStatus(BrokerageRecordStatusEnum.CLOSED.getValue());
                updateObj.setUnfreezeTime(LocalDateTime.now());
                int updateRows = brokerageRecordMapper.updateByIdAndStatus(record.getId(), record.getStatus(), updateObj);
                if (updateRows == 0) {
                    log.error("[unfreezeUserRecord][record({}) 更新为已失效失败]", record.getId());
                    return false;
                }
                return false;
            }
            updateObj.setStatus(BrokerageRecordStatusEnum.UNFREEZE.getValue());
            updateObj.setUnfreezeTime(LocalDateTime.now());
            int updateRows = brokerageRecordMapper.updateByIdAndStatus(record.getId(), record.getStatus(), updateObj);
            if (updateRows == 0) {
                log.error("[unfreezeUserRecord][record({}) 更新为已结算失败]", record.getId());
                return false;
            }
            // 增加用户累计业绩、累计佣金
            updateRows = brokerageUserMapper.increaseBonusMoney(record.getUserId(), record.getBasePrice(), record.getBonusMoney());
            log.info("[unfreezeUserRecord][record({}) 更新为已结算结果：{}]", record.getId(), updateRows > 0);
            if (updateRows == 0) {
                return false;
            }
            String tradeNo = record.getBizId();
            if (tradeNo.contains("@")) {
                tradeNo = tradeNo.split("@")[0];
            }
            brokerageRecordProducer.sendCommissionUnfreezeMessage(record.getUserId(), tradeNo, record.getBasePrice(), record.getBonusMoney());
            return true;
        });
        return Boolean.TRUE.equals(result);
    }

}
